package org.yohailong.javabase;

import com.alibaba.fastjson2.JSON;
import org.yohailong.javabase.dynamiclambda.DynamicTime;
import org.yohailong.javabase.dynamiclambda.SFunction;

import java.lang.invoke.*;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * @author 朱海龙
 * 2025/6/3 15:38
 */
public class JavaBaseRun {


    public static void main(String[] args) {

        try {

            MethodHandles.Lookup lookup = MethodHandles.lookup();

            MethodType rawMethodType = MethodType.methodType(Object.class, Object.class);

            MethodHandle getDynamicTime = lookup.findVirtual(DynamicTime.class, "getDynamicTime", MethodType.methodType(Date.class));

            MethodType actMethodType = MethodType.methodType(Date.class, DynamicTime.class);

            CallSite callSite = LambdaMetafactory.altMetafactory(lookup, "apply", MethodType.methodType(SFunction.class), rawMethodType, getDynamicTime, actMethodType, LambdaMetafactory.FLAG_SERIALIZABLE | LambdaMetafactory.FLAG_MARKERS, 3,
                    Runnable.class, Consumer.class, Supplier.class);
            //CallSite callSite = LambdaMetafactory.metafactory(lookup, "apply", MethodType.methodType(SFunction.class), rawMethodType, getDynamicTime, actMethodType);

            SFunction<DynamicTime, Date> filedInvoke = (SFunction<DynamicTime, Date>) callSite.getTarget()
                                                                                              .invokeExact();
            Date date = filedInvoke.apply(new DynamicTime());

            System.out.println(date);
            //
            //Method method = filedInvoke.getClass().getDeclaredMethod("writeReplace");
            //method.setAccessible(true);

            //SerializedLambda invoke = (SerializedLambda) method.invoke(filedInvoke);

            //System.out.println(JSONObject.toJSONString(invoke));

            Method declaredMethods = filedInvoke.getClass()
                                                .getDeclaredMethod("writeReplace");
            declaredMethods.setAccessible(true);

            Class<?>[] parameterTypes = declaredMethods.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println(parameterType.getName());
            }

            Object invoke = declaredMethods.invoke(filedInvoke);
            System.out.println(JSON.toJSONString(invoke));

        } catch (Throwable e) {
            e.printStackTrace();
        }


    }


    private static void printInterface(Class<?> clazz) {
        if (Objects.isNull(clazz) || clazz.equals(Object.class)) {
            return;
        }
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface.getName());
        }
        Class<?> superclass = clazz.getSuperclass();
        printInterface(superclass);
    }
}
